package com.yricky.memoria.ui.component

import android.os.Handler
import android.os.Looper
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.yricky.memoria.data.*
import com.yricky.memoria.data.pojo.PdfQuery
import com.yricky.memoria.data.pojo.SectionQuery
import com.yricky.memoria.utils.Executor
import com.yricky.memoria.utils.PdfDoc
import com.yricky.memoria.utils.gson
import com.yricky.memoria.utils.ws
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.InputStream

/**
 * @author Yricky
 * @date 2021/12/3
 */
class SectionViewModel:ViewModel() {
    private val handler:Handler = Handler(Looper.getMainLooper())

    private val _section:MutableLiveData<Section> by lazy{
        MutableLiveData<Section>().also {
            it.observeForever { sec ->
                _viewState.value = _viewState.value.copy(
                    isEditMode = sec?.jsonData?.items?.size ?: 0 == 0,
                    items = sec?.jsonData?.items ?: emptyList(),
                    title = "${sec?.metaData?.name}"
                )
                queryPdfList()
            }
        }
    }
    fun setRequest(section: SectionQuery):Boolean{
        viewModelScope.launch {
            _section.value=withContext(Dispatchers.IO){
                ws.getSection(section)
            }
        }
        return true
    }


    data class ViewState(
        val isEditMode:Boolean = false,
        val title:String = "",
        val items:List<Section.Item> = emptyList(),
        val pdfList:List<Pair<String,PdfDoc>> = emptyList()
    )
    private val _viewState:MutableStateFlow<ViewState> = MutableStateFlow(ViewState())
    val viewState = _viewState.asStateFlow()


    sealed class Action{
        object Save : Action()
        class EditMode(val isEdit:Boolean) :Action()
        class AddTextItem(val index:Int = -1,val content:String = "") :Action()
        class AddImgItem(val index: Int=-1,val inS:InputStream) :Action()
        class AddSectionItem(val index:Int = -1,val query:SectionQuery):Action()
        class AddPdfPageItem(val index: Int=-1,val pdfName:String,val pageIndex:Int? = null):Action()
        class MoveItem(val item: Section.Item,val up:Boolean):Action()
        class RemoveItem(val item:Section.Item) :Action()
    }

    fun onAction(action:Action){
        when(action){
            is Action.Save -> save()
            is Action.AddTextItem ->{
                val index =  if(action.index == -1){
                    _viewState.value.items.size
                }else action.index
                addTextItem(index,action.content)
            }
            is Action.AddImgItem ->{
                val index =  if(action.index == -1){
                    _viewState.value.items.size
                }else action.index
                addImageItem(index,action.inS)
            }
            is Action.AddSectionItem -> {
                val index =  if(action.index == -1){
                    _viewState.value.items.size
                }else action.index
                _viewState.value = _viewState.value.copy(
                    items = _viewState.value.items.toMutableList().apply {
                        add(index, Section.Item(
                            type = Section.Item.TYPE_SECTION,
                            content = gson.toJson(action.query)
                        ))
                    }
                )
                save()
            }
            is Action.EditMode ->{
                _viewState.value = _viewState.value.copy(isEditMode = action.isEdit)
            }
            is Action.MoveItem ->{
                val index = _viewState.value.items.indexOf(action.item)
                if(index!= 0 && action.up){
                    _viewState.value = _viewState.value.copy(
                        items = _viewState.value.items.toMutableList().apply {
                            removeAt(index)
                            add(index-1,action.item)
                        }
                    )

                } else if(index != _viewState.value.items.size-1 && !action.up){
                    _viewState.value = _viewState.value.copy(
                        items = _viewState.value.items.toMutableList().apply {
                            removeAt(index)
                            add(index+1,action.item)
                        }
                    )
                }
                save()
            }
            is Action.RemoveItem -> {
                removeItem(action.item)
            }
            is Action.AddPdfPageItem -> {
                val index =  if(action.index == -1){
                        _viewState.value.items.size
                    }else action.index
                _viewState.value = _viewState.value.copy(
                    items = _viewState.value.items.toMutableList().apply {
                        _section.value?.let {
                            add(index, Section.Item(
                                    type = Section.Item.TYPE_PDF,
                                    content = gson.toJson(PdfQuery(it.model.metaData, action.pdfName))
                                )
                            )
                        }
                    }
                )
                save()
            }
        }
    }

    private fun addTextItem(index:Int = _viewState.value.items.size,content:String){
        _viewState.value = _viewState.value.copy(
            items = _viewState.value.items.toMutableList().apply {
                add(index,Section.EmptyTextItem.also {
                    it.content = content
                })
            }
        )
        save()
    }


    private fun addImageItem(index:Int = _viewState.value.items.size, inS:InputStream){
        viewModelScope.launch {
            _viewState.value = withContext(Dispatchers.IO){
                _viewState.value.copy(
                    items = _viewState.value.items.toMutableList().apply {
                        val name = "${System.currentTimeMillis()}"
                        File(_section.value?.assetsDir,name).writeBytes(inS.readBytes())
                        add(index, Section.imageItem(name))
                    }
                )
            }
            save()
        }

    }

    private fun removeItem(item:Section.Item){
        viewModelScope.launch {
            _viewState.value = withContext(Dispatchers.IO){
                _viewState.value.copy(
                    items = _viewState.value.items.toMutableList().apply {
                        remove(item)
                        if(item.type == Section.Item.TYPE_IMG){
                            File(getContentPath(item.content)).delete()
                        }
                    }
                )
            }
            save()
        }
    }

    fun getContentPath(assetName: String):String{
        return _section.value?.getContentPath(assetName) ?: ""
    }

    val wsModel:WorkSpaceModel? get() = _section.value?.model?.model

    private fun save(){
        handler.removeMessages(0)
        val sec = _section.value
        val list = _viewState.value.items
        handler.postDelayed({
            Executor.exec{
                sec?.apply {
                    jsonData.items=list
                    save()
                }
            }
        },1000)
    }

    private fun queryPdfList() {
        viewModelScope.launch {
            val subjectModel = _section.value?.model
            val list = withContext(Dispatchers.IO) {
                subjectModel?.pdfList() ?: emptyList()
            }
            _viewState.value = _viewState.value.copy(pdfList = list)
        }
    }
}